package com.dashu.base.utils.File;

import com.dashu.base.utils.SystemUtils;
import com.dashu.base.utils.encryption.Base64;
import com.sun.security.auth.login.ConfigFile;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

@Slf4j
public class FileUtils extends ConfigFile {


    /**
     * 下载文件
     *
     * @param url      下载地址
     * @param path     保存路径 后面没有/
     * @param filename 文件名称
     * @return
     */
    public static String downPic(String url, String path, String filename) {
        HttpURLConnection conn = null;
        InputStream inputStream = null;
        BufferedInputStream bis = null;
        FileOutputStream out = null;
        try {
            File file = new File(path);
            if (!file.isDirectory() && !file.exists()) {
                file.mkdirs();
            }
            file = new File(path + File.separatorChar + filename);
            out = new FileOutputStream(file);
            // 建立链接
            URL httpUrl = new URL(url);
            conn = (HttpURLConnection) httpUrl.openConnection();
            //以Post方式提交表单，默认get方式
            conn.setRequestMethod("GET");
            conn.setDoInput(true);
            conn.setDoOutput(true);
            // post方式不能使用缓存
            conn.setUseCaches(false);
            //连接指定的资源
            conn.connect();
            //获取网络输入流
            inputStream = conn.getInputStream();
            bis = new BufferedInputStream(inputStream);
            byte b[] = new byte[1024];
            int len = 0;
            while ((len = bis.read(b)) != -1) {
                out.write(b, 0, len);
            }
            System.out.println("下载完成...");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (bis != null) {
                    bis.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return filename;
    }

    /**
     * 判读路径是否存在
     *
     * @param dirPath
     */
    public static boolean isPathExist(String dirPath) {
        File file = new File(dirPath);
        if (!file.exists()) {
            return file.mkdirs();
        }
        return true;
    }

    /**
     * 判读文件是否存在
     *
     * @param dirPath
     */
    public static boolean isFileExist(String dirPath) {
        File file = new File(dirPath);
        return file.exists();
    }


    /**
     * 将内容写入文件
     *
     * @param filePath
     * @param content
     */
    public static boolean writeFile(String filePath, String content) {
//        File file = new File(filePath);
//        FileWriter fw = null;
//
//        if (!file.isFile())
//            return false;
//        try {
//            boolean isCreate;
//            if (file.exists())
//                file.delete();
//
//            isCreate = file.createNewFile();
//            if (!isCreate)
//                return false;
//
//            fw = new FileWriter(file, false); // true表示追加
//            fw.write(content);//向文件中写内容
//            fw.flush();
//            logger.debug("写数据到文件成功");
//        } catch (IOException e) {
//            logger.error("writeFile", e);
//            return false;
//        } finally {
//            if (fw != null) {
//                try {
//                    fw.close();
//                } catch (IOException e) {
//                    logger.error("writeFile", e);
//                }
//            }
//        }
//        return true;


        FileOutputStream fos = null;
        File file;
        try {
            // 指定写入文件的路径
            file = new File(filePath);
            /* 先检测文件是否存在，如果不存在则先创建*/
            if (!file.exists()) {
                file.createNewFile();
            }


            fos = new FileOutputStream(file);

            /*
             * 字符串的内容没法直接写到文件，我们需要先使用getBytes转换为bytes。
             */
            byte[] bytesArray = content.getBytes();
            fos.write(bytesArray);
            fos.flush();
            System.out.println("File Written Successfully");
        } catch (IOException e) {
            log.error("writeFile", e);
            return false;
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException ioe) {
                System.out.println("Error in closing the Stream");
            }
        }
        return true;
    }

    /**
     * 读取文件内容
     *
     * @param filePath
     * @return
     */
    public static String readFile(String filePath) {
        File file = new File(filePath);
        Long filelength = file.length();
        byte[] filecontent = new byte[filelength.intValue()];
        try {
            FileInputStream in = new FileInputStream(file);
            in.read(filecontent);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new String(filecontent, Charset.forName("utf-8"));
    }

    /**
     * 压缩文件
     *
     * @param printPath
     * @param sourceDir
     */
    public static void zipDir(String printPath, String sourceDir) {
        if (!new File(sourceDir).isDirectory())
            return;

        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(new FileOutputStream(printPath));
            File[] files = new File(sourceDir).listFiles();
            if (files != null) {
                for (File srcFile : files) {
                    byte[] buf = new byte[2 * 1024];
                    zos.putNextEntry(new ZipEntry(srcFile.getName()));
                    int len;
                    FileInputStream in = new FileInputStream(srcFile);
                    while ((len = in.read(buf)) != -1) {
                        zos.write(buf, 0, len);
                    }
                    zos.closeEntry();
                    in.close();
                }
                long end = System.currentTimeMillis();
                System.out.println("压缩完成，耗时：" + (end - start) + " ms");
            }
        } catch (Exception e) {
            throw new RuntimeException("zip error from ZipUtils", e);
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 删除文件夹里面文件
     *
     * @param path
     * @return
     */
    public static boolean delDirtory(String path) {
        File file = new File(path);
        if (file.isDirectory()) {

            File[] files = file.listFiles();

            if (files == null)
                return true;

            for (File file1 : files) {
                boolean isResult = file1.delete();
            }
            return true;
        }
        return false;
    }


    /**
     * zip解压
     *
     * @param srcFile     zip源文件
     * @param destDirPath 解压后的目标文件夹
     * @throws RuntimeException 解压失败会抛出运行时异常
     */
    public static void unZip(File srcFile, String destDirPath) throws RuntimeException {
        long start = System.currentTimeMillis();
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
        }
        // 开始解压
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(srcFile);
            Enumeration<?> entries = zipFile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) entries.nextElement();
                System.out.println("解压" + entry.getName());
                // 如果是文件夹，就创建个文件夹
                if (entry.isDirectory()) {
                    String dirPath = destDirPath + "/" + entry.getName();
                    File dir = new File(dirPath);
                    dir.mkdirs();
                } else {
                    // 如果是文件，就先创建一个文件，然后用io流把内容copy过去
                    File targetFile = new File(destDirPath + "/" + entry.getName());
                    // 保证这个文件的父文件夹必须要存在
                    if (!targetFile.getParentFile().exists()) {
                        targetFile.getParentFile().mkdirs();
                    }
                    targetFile.createNewFile();
                    // 将压缩文件内容写入到这个文件中
                    InputStream is = zipFile.getInputStream(entry);
                    FileOutputStream fos = new FileOutputStream(targetFile);
                    int len;
                    byte[] buf = new byte[102400];
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }
                    // 关流顺序，先打开的后关闭
                    fos.close();
                    is.close();
                }
            }
            long end = System.currentTimeMillis();
            System.out.println("解压完成，耗时：" + (end - start) + " ms");
        } catch (Exception e) {
            throw new RuntimeException("unzip error from ZipUtils", e);
        } finally {
            if (zipFile != null) {
                try {
                    zipFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 监听实时更改文件的内容
     *
     * @param listener 监听对象
     * @param path     文件路径
     */
    public static void setFileListener(FileListener listener, String path) {
        if (listener == null)
            return;

        File file = new File(path);
        if (file.listFiles() != null && file.listFiles().length > 0) {
            for (File files : file.listFiles()) {
                try {
                    onFileListener(path, files.getName(), listener);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        try {
            // 获取监视器
            WatchService newWatchService = FileSystems.getDefault().newWatchService();
            // 注册监视器，监控目录下的文件创建、删除和修改操作
            Paths.get(path).register(newWatchService,
                    StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE,
                    StandardWatchEventKinds.ENTRY_MODIFY);

            Set<String> fileNameSet = new HashSet<>(); //Set去重，当添加文件的时候，修改时间也会被监听执行
            while (true) {
                System.out.println("siteListener开始监听");
                // 获取下一个文件改动事件
                WatchKey take = newWatchService.take();
                // 获取文件改动步骤
                for (WatchEvent<?> event : take.pollEvents()) {
                    fileNameSet.add(event.context() + "");

                }
                for (String name : fileNameSet) {
//                    System.out.println("文件更新：" + path + File.separatorChar + name.replace(".swp" , "").replace("\\." , ""));
                    onFileListener(path, name, listener);
                }

                // 重设WatchKey
                boolean reset = take.reset();
                System.out.println("key reset:" + reset);
                System.out.println();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


//        WatchService watchService = null;
//        try {
//            // 获取文件系统的WatchService对象
//            watchService = FileSystems.getDefault().newWatchService();
//            // 监听filePath目录下文件是否修改或增加；register()方法后面监听事件种类还可以增加、删除。
//            Paths.get(path).register(watchService, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_CREATE); //监听修改、添加
//        } catch (Exception e) {
//            e.printStackTrace();
//            return;
//        }
//
//        // 设置后台线程
//        WatchService finalWatchService = watchService;
//        Thread watchThread = new Thread(new Runnable() {
//
//            private Set<String> fileNameSet = new HashSet<>(); //Set去重，当添加文件的时候，修改时间也会被监听执行
//
//            @Override
//            public void run() {
//                while (true) {
//                    try {
//                        // 获取下一个文件改动事件
//                        WatchKey key = finalWatchService.take();
//                        for (WatchEvent<?> event : key.pollEvents()) {
//                            fileNameSet.add(event.context() + "");
//                        }
//                        for (String name : fileNameSet) {
//                            System.out.println("文件更新：" + path + File.separatorChar + name);
//                            onFileListener(path , name , listener);
//                        }
//                        // 重设WatchKey
//                        boolean valid = key.reset();
//                        fileNameSet.clear();
//
//                        // 如果重设失败，退出监听
//                        if (!valid) {
//                            break;
//                        }
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                    }
//                }
//            }
//        });
//
//        // 设置为后台守护线程
//        watchThread.setDaemon(true);
//        watchThread.start();
    }

    private static void onFileListener(String path, String name, FileListener listener) throws Exception {
        InputStreamReader file = new InputStreamReader(new FileInputStream(path + File.separatorChar + name));
        BufferedReader br = new BufferedReader(file);
        String data = null;
        Map<String, String> filename = new HashMap<>();
        while ((data = br.readLine()) != null) {
            System.out.println(data.trim());
            if (data.trim().startsWith("#")) //以#开头作为注释
                continue;
            String[] args = data.split("=");
            if (args.length != 2)
                continue;
            String dataKey = args[0].trim();
            String dataValue = args[1].trim();
            filename.put(dataKey, dataValue);
        }
        //关闭
        file.close();
        br.close();
        listener.onTextChange(filename, name);
    }


    public static void main(String[] args) {
//        setFileListener(new FileListener() {
//            @Override
//            public void onTextChange(Map<String, String> map, String fileName) {
//                System.out.println(map.toString());
//                System.out.println(fileName);
//            }
//        }, "C:\\Users\\Administrator\\Desktop\\111");
//        while (true) {
//        }
        String fileName = "/Dashu_sy/sy_data/file:/Dashu_sy/sy_data/sy_data.jar!/BOOT-INF/lib/BaseCommon-1.0.27.jar!";
        String[] s = fileName.split("!")[0].split("/");
        System.out.println(s[s.length - 1]);
    }

    /**
     * 获取项目路径
     *
     * @return
     */
    public static String getProjectPath() {
        URL url = SystemUtils.class.getProtectionDomain().getCodeSource().getLocation();
        String filePath = null;
        try {
            filePath = java.net.URLDecoder.decode(url.getPath(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (filePath == null)
            return null;

        if (filePath.endsWith(".jar"))
            filePath = filePath.substring(0, filePath.lastIndexOf("/") + 1);
        File file = new File(filePath);
        filePath = file.getAbsolutePath();
        return filePath;
    }


    /**
     * 获取项目路径
     *
     * @return
     */
    public static String getProjectPath2() {
        URL url = SystemUtils.class.getProtectionDomain().getCodeSource().getLocation();
        String filePath = null;
        try {
            filePath = java.net.URLDecoder.decode(url.getPath(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (filePath == null)
            return null;

        if (filePath.endsWith(".jar"))
            filePath = filePath.substring(0, filePath.lastIndexOf("/") + 1);

        File file = new File(filePath);
        filePath = file.getAbsolutePath();

        System.out.println(Arrays.toString(filePath.split("/file:")));
        filePath = filePath.split("/file:")[0];
        return filePath;
    }


    /**
     * 获取项目路径
     *
     * @return
     */
    public static String getProjectName() {
        URL url = SystemUtils.class.getProtectionDomain().getCodeSource().getLocation();
        String fileName = null;
        try {
            fileName = java.net.URLDecoder.decode(url.getPath(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (fileName == null)
            return null;
        File file = new File(fileName);
        return file.getName();
    }


    /**
     * 获取项目路径
     *
     * @return
     */
    public static String getProjectName2() {
        URL url = SystemUtils.class.getProtectionDomain().getCodeSource().getLocation();
        String fileName = null;
        try {
            fileName = java.net.URLDecoder.decode(url.getPath(), "utf-8");

            if (fileName == null)
                return null;
            if (fileName.endsWith(".jar"))
                fileName = fileName.substring(0, fileName.lastIndexOf("/") + 1);

            File file = new File(fileName);
            fileName = file.getAbsolutePath();

            String[] s = fileName.split("!")[0].split("/");
            fileName = s[s.length - 1];
        } catch (Exception e) {
            return null;
        }
        return fileName;
    }


    /**
     * 获取项目的大小
     *
     * @return
     */
    public static long getProjectSize() {
        File file = new File(getProjectPath() + File.separatorChar + getProjectName());
        return file.length();
    }


    /**
     * 获取项目的大小
     *
     * @return
     */
    public static long getProjectSize2() {
        File file = new File(getProjectPath2() + File.separatorChar + getProjectName2());
        return file.length();
    }


    public static File downloadWxImage(String url) {
        File file = null;

        URL urlfile;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            file = File.createTempFile("wx_image", ".png");
            //下载
            urlfile = new URL(url);
            inputStream = urlfile.openStream();
            outputStream = new FileOutputStream(file);

            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != outputStream) {
                    outputStream.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }



}
